package jnpf.engine.service.impl;

import jnpf.base.UserInfo;
import jnpf.database.model.dto.PrepareSqlDTO;
import jnpf.database.model.entity.DbLinkEntity;
import jnpf.database.util.JdbcUtil;
import jnpf.engine.entity.FlowEngineEntity;
import jnpf.engine.entity.FlowTaskEntity;
import jnpf.engine.model.DataModel;
import jnpf.engine.model.flowengine.FlowModel;
import jnpf.engine.model.flowtask.FlowTaskInfoVO;
import jnpf.engine.service.FlowDynamicService;
import jnpf.engine.service.FlowEngineService;
import jnpf.engine.service.FlowTaskNewService;
import jnpf.engine.service.FlowTaskService;
import jnpf.engine.util.FlowDataUtil;
import jnpf.engine.util.OnlineDevFormUtils;
import jnpf.engine.util.ServiceAllUtil;
import jnpf.exception.WorkFlowException;
import jnpf.model.*;
import jnpf.model.visiual.FormCloumnUtil;
import jnpf.model.visiual.FormDataModel;
import jnpf.model.visiual.RecursionForm;
import jnpf.model.visiual.TableModel;
import jnpf.model.visiual.fields.FieLdsModel;
import jnpf.util.*;
import lombok.Cleanup;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Connection;
import java.util.*;

/**
 * 在线开发工作流
 *
 * @author JNPF开发平台组
 * @version V3.1.0
 * @copyright 引迈信息技术有限公司
 * @date 2021/3/15 9:19
 */
@Slf4j
@Service
public class FlowDynamicServiceImpl implements FlowDynamicService {

    @Autowired
    private FlowTaskService flowTaskService;
    @Autowired
    private FlowEngineService flowEngineService;
    @Autowired
    private FlowTaskNewService flowTaskNewService;
    @Autowired
    private UserProvider userProvider;
    @Autowired
    private FlowDataUtil flowDataUtil;
    @Autowired
    private ServiceAllUtil serviceUtil;

    @Override
    public FlowTaskInfoVO info(FlowTaskEntity entity, String taskOperatorId) throws WorkFlowException {
        FlowEngineEntity flowEntity = flowEngineService.getInfo(entity.getFlowId());
        List<TableModel> tableModelList = JsonUtil.getJsonToList(flowEntity.getFlowTables(), TableModel.class);
        FlowTaskInfoVO vo = JsonUtil.getJsonToBean(entity, FlowTaskInfoVO.class);
        //formTempJson
        FormDataModel formData = JsonUtil.getJsonToBean(entity.getFlowForm(), FormDataModel.class);
        List<FieLdsModel> list = JsonUtil.getJsonToList(formData.getFields(), FieLdsModel.class);
        DbLinkEntity link = serviceUtil.getDbLink(flowEntity.getDbLinkId());
        Map<String, Object> dataMap = StringUtil.isNotEmpty(entity.getFlowFormContentJson()) ? JsonUtil.stringToMap(entity.getFlowFormContentJson()) : new HashMap<>(16);
        Boolean concurrencyLock = formData.getConcurrencyLock();
        Integer primaryKeyPolicy = formData.getPrimaryKeyPolicy();
        DataModel dataModel = DataModel.builder().dataNewMap(dataMap).fieLdsModelList(list).tableModelList(tableModelList).mainId(entity.getId()).link(link).concurrencyLock(concurrencyLock).primaryKeyPolicy(primaryKeyPolicy).build();
        Map<String, Object> result = flowDataUtil.info(dataModel);
        vo.setData(JsonUtil.getObjectToString(result));
        return vo;
    }

    @Override
    public void save(String id, FlowModel flowModel) throws WorkFlowException {
        String flowId = flowModel.getFlowId();
        String data = flowModel.getData();
        FlowEngineEntity entity = flowEngineService.getInfo(flowId);
        UserInfo userInfo = userProvider.get();
        String billNo = "单据规则不存在";
        String flowTitle = userInfo.getUserName() + "的" + entity.getFullName();//更新标题
        String processId = RandomUtil.uuId();
        //tableJson
        List<TableModel> tableModelList = JsonUtil.getJsonToList(entity.getFlowTables(), TableModel.class);
        //formTempJson
        FormDataModel formData = JsonUtil.getJsonToBean(entity.getFormData(), FormDataModel.class);
        List<FieLdsModel> list = JsonUtil.getJsonToList(formData.getFields(), FieLdsModel.class);
        RecursionForm recursionForm = new RecursionForm(list, tableModelList);
        List<FormAllModel> formAllModel = new ArrayList<>();
        FormCloumnUtil.recursionForm(recursionForm, formAllModel);
        //主表的单据数据
        boolean type = id != null;
        if (type) {
            processId = id;
        }
        //表单值
        Map<String, Object> dataMap = JsonUtil.stringToMap(data);
        DbLinkEntity link = serviceUtil.getDbLink(entity.getDbLinkId());
        TableModel tableModel = tableModelList.stream().filter(t -> "1".equals(t.getTypeId())).findFirst().orElse(null);
        Boolean concurrencyLock = formData.getConcurrencyLock();
        Integer primaryKeyPolicy = formData.getPrimaryKeyPolicy();
        if (type && concurrencyLock) {
            getVersion(link, tableModel.getTable(), id, dataMap,primaryKeyPolicy);
            Integer f_version = dataMap.get("f_version") != null ? Integer.valueOf(String.valueOf(dataMap.get("f_version"))) : 0;
            dataMap.put("f_version", f_version + 1);
        } else {
            dataMap.put("f_version", dataMap.get("f_version") != null ? dataMap.get("f_version") : 0);
        }
        DataModel dataModel = DataModel.builder().dataNewMap(dataMap).fieLdsModelList(list).tableModelList(tableModelList).mainId(processId).link(link).userInfo(userInfo).concurrencyLock(concurrencyLock).primaryKeyPolicy(primaryKeyPolicy).build();
        int num = type ? 1 : 0;
        boolean b = OnlineDevFormUtils.checkForm(list, dataMap, link, tableModelList,primaryKeyPolicy, id);
        if (!b) {
            throw new WorkFlowException("单行输入不能重复");
        }
        Map<String, Object> result = type ? flowDataUtil.update(dataModel) : flowDataUtil.create(dataModel);
        dataMap.putAll(result);
        flowModel(flowModel, id, processId, flowTitle, dataMap, billNo, userInfo);
        flowModel.setFlowUrgent(1);
        flowTaskNewService.save(flowModel);
    }

    @Override
    public void submit(String id, FlowModel flowModel) throws WorkFlowException {
        String flowId = flowModel.getFlowId();
        String data = flowModel.getData();
        FlowEngineEntity entity = flowEngineService.getInfo(flowId);
        UserInfo userInfo = userProvider.get();
        String billNo = "单据规则不存在";
        String flowTitle = userInfo.getUserName() + "的" + entity.getFullName();
        //更新标题
        String processId = RandomUtil.uuId();
        //tableJson
        List<TableModel> tableModelList = JsonUtil.getJsonToList(entity.getFlowTables(), TableModel.class);
        //formTempJson
        FormDataModel formData = JsonUtil.getJsonToBean(entity.getFormData(), FormDataModel.class);
        List<FieLdsModel> list = JsonUtil.getJsonToList(formData.getFields(), FieLdsModel.class);
        List<FormAllModel> formAllModel = new ArrayList<>();
        RecursionForm recursionForm = new RecursionForm(list, tableModelList);
        FormCloumnUtil.recursionForm(recursionForm, formAllModel);
        //主表的单据数据
        boolean type = id != null;
        if (type) {
            processId = id;
        }
        //表单值
        Map<String, Object> dataMap = JsonUtil.stringToMap(data);
        DbLinkEntity link = serviceUtil.getDbLink(entity.getDbLinkId());
        TableModel tableModel = tableModelList.stream().filter(t -> "1".equals(t.getTypeId())).findFirst().orElse(null);
        Boolean concurrencyLock = formData.getConcurrencyLock();
        Integer primaryKeyPolicy = formData.getPrimaryKeyPolicy();
        if (type && concurrencyLock) {
            getVersion(link, tableModel.getTable(), id, dataMap,primaryKeyPolicy);
            Integer f_version = dataMap.get("f_version") != null ? Integer.valueOf(String.valueOf(dataMap.get("f_version"))) : 0;
            dataMap.put("f_version", f_version + 1);
        } else {
            dataMap.put("f_version", dataMap.get("f_version") != null ? dataMap.get("f_version") : 0);
        }

        DataModel dataModel = DataModel.builder().dataNewMap(dataMap).fieLdsModelList(list).tableModelList(tableModelList).mainId(processId).link(link).userInfo(userInfo).concurrencyLock(concurrencyLock).primaryKeyPolicy(primaryKeyPolicy).build();
        int num = type ? 1 : 0;
        boolean b = OnlineDevFormUtils.checkForm(list, dataMap, link, tableModelList,primaryKeyPolicy, id);
        if (!b) {
            throw new WorkFlowException("单行输入不能重复");
        }
        Map<String, Object> result = type ? flowDataUtil.update(dataModel) : flowDataUtil.create(dataModel);
        dataMap.putAll(result);
        flowModel(flowModel, id, processId, flowTitle, dataMap, billNo, userInfo);
        flowTaskNewService.submit(flowModel);
    }

    @Override
    public Map<String, Object> getData(String flowId, String id) throws WorkFlowException {
        FlowTaskEntity entity = flowTaskService.getInfo(id);
        FlowEngineEntity flowentity = flowEngineService.getInfo(flowId);
        List<TableModel> tableModelList = JsonUtil.getJsonToList(flowentity.getFlowTables(), TableModel.class);
        //formTempJson
        FormDataModel formData = JsonUtil.getJsonToBean(entity.getFlowForm(), FormDataModel.class);
        List<FieLdsModel> list = JsonUtil.getJsonToList(formData.getFields(), FieLdsModel.class);
        DbLinkEntity link = serviceUtil.getDbLink(flowentity.getDbLinkId());
        Map<String, Object> dataMap = StringUtil.isNotEmpty(entity.getFlowFormContentJson()) ? JsonUtil.stringToMap(entity.getFlowFormContentJson()) : new HashMap<>(16);
        DataModel dataModel = DataModel.builder().dataNewMap(dataMap).fieLdsModelList(list).tableModelList(tableModelList).mainId(entity.getId()).link(link).convert(true).concurrencyLock(formData.getConcurrencyLock()).build();
        Map<String, Object> resultData = flowDataUtil.info(dataModel);
        return resultData;
    }

    /**
     * 赋值流程
     */
    private void flowModel(FlowModel flowModel, String id, String processId, String flowTitle, Map<String, Object> data, String billNo, UserInfo userInfo) {
        flowModel.setId(id);
        flowModel.setProcessId(processId);
        flowModel.setFlowTitle(flowTitle);
        flowModel.setBillNo(billNo);
        flowModel.setFormData(data);
        flowModel.setUserInfo(userInfo);
    }

    /**
     * 获取版本号
     *
     * @throws WorkFlowException
     */
    private void getVersion(DbLinkEntity dbLink, String table, String id, Map<String, Object> dataMap,int primaryKeyPolicy) throws WorkFlowException {
        boolean version = true;
        try {
            @Cleanup Connection conn = flowDataUtil.getTableConn(dbLink);
            String pKeyName = flowDataUtil.getKey(conn, table, primaryKeyPolicy);
            String queryVersionSql = "select f_version from " + table + " where " + pKeyName + " = ?";
            PrepareSqlDTO statementDTO = new PrepareSqlDTO(conn, queryVersionSql, id);
            Map<String, Object> map = JdbcUtil.queryOne(statementDTO);
            //数据库为Oracle大小写敏感，需要将key转换成小写来判断
            version = String.valueOf(this.transFormLowerCase(map).get("f_version")).equals(String.valueOf(dataMap.get("f_version")));
        } catch (Exception e) {
            System.out.println(e.getMessage());
            log.error("查询并发锁异常" + e.getMessage());
        }
        if (!version) {
            throw new WorkFlowException("当前表单原数据已被调整,请重新进入该页面编辑并提交数据");
        }
    }
    /**
     * map key转换成小写
     * @param map
     * @return map
     * @copyright 引迈信息技术有限公司
     * @date 2022/11/2
     */
    private Map<String,Object> transFormLowerCase(Map<String,Object> map){
        Map<String,Object> resultMap=new HashMap<>();
        if(map==null||map.isEmpty()){
            return resultMap;
        }
        Set<String> keySet=map.keySet();
        for(String key:keySet){
            resultMap.put(key.toLowerCase(),map.get(key));
        }
        return resultMap;
    }

}
